package com.wang.jmonkey.redis.utils;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import java.util.concurrent.TimeUnit;

/**
 * @Description 基于Redission的分布式锁工具类
 * @Author HeJiawang
 * @Date 2021/5/11 14:44
 */
public class RedissonLocker implements Locker {

	private RedissonClient redissonClient;
	
	public RedissonLocker(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
	}

	public void setRedissonClient(RedissonClient redissonClient) {
		this.redissonClient = redissonClient;
	}

	/**
	 * 获取锁，如果锁不可用，则当前线程处于休眠状态，直到获得锁为止。
	 * @param lockKey lockKey
	 */
	@Override
	public void lock(String lockKey) {
		RLock lock = redissonClient.getLock(lockKey);
		lock.lock();
	}

	/**
	 * 释放锁
	 * @param lockKey lockKey
	 */
	@Override
	public void unlock(String lockKey) {
		RLock lock = redissonClient.getLock(lockKey);
		lock.unlock();
	}

	/**
	 * 获取锁,如果锁不可用，则当前线程处于休眠状态，直到获得锁为止。如果获取到锁后，执行结束后解锁或达到超时时间后会自动释放锁
	 * @param lockKey lockKey
	 * @param timeout 超时时间
	 */
	@Override
	public void lock(String lockKey, int timeout) {
		 RLock lock = redissonClient.getLock(lockKey);
		 lock.lock(timeout, TimeUnit.SECONDS);
	}

	/**
	 * 获取锁,如果锁不可用，则当前线程处于休眠状态，直到获得锁为止。如果获取到锁后，执行结束后解锁或达到超时时间后会自动释放锁
	 *
	 * @param lockKey lockKey
	 * @param unit 超时时间单位
	 * @param timeout 超时时间
	 */
	@Override
	public void lock(String lockKey, TimeUnit unit, int timeout) {
		RLock lock = redissonClient.getLock(lockKey);
		lock.lock(timeout, unit);
	}

	/**
	 * 尝试获取锁，获取到立即返回true,未获取到立即返回false
	 * @param lockKey lockKey
	 * @return boolean
	 */
	@Override
	public boolean tryLock(String lockKey) {
		RLock lock = redissonClient.getLock(lockKey);
		return lock.tryLock();
	}

	/**
	 * 尝试获取锁，在等待时间内获取到锁则返回true,否则返回false,如果获取到锁，则要么执行完后程序释放锁，要么在给定的超时时间leaseTime后释放锁
	 * @param lockKey lockKey
	 * @param waitTime 等待时间
	 * @param leaseTime 超时时间
	 * @param unit 时间单位
	 * @return
	 */
	@Override
	public boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
		RLock lock = redissonClient.getLock(lockKey);
		return lock.tryLock(waitTime, leaseTime, unit);
	}

	/**
	 * 锁是否被任意一个线程锁持有
	 * @param lockKey lockKey
	 * @return boolean
	 */
	@Override
	public boolean isLocked(String lockKey) {
		RLock lock = redissonClient.getLock(lockKey);
		return lock.isLocked();
	}

}
